package net.wanglu.www.zzz.rule.pronoun;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.regex.Matcher;

import net.wanglu.www.zzz.rule.BadEgg;
import net.wanglu.www.zzz.rule.Rule;
import net.wanglu.www.zzz.service.se.__SentenceElements;
import net.wanglu.www.zzz.service.se.nsubj._NSubjTuple;
import net.wanglu.www.zzz.service.se.obj._ObjectTuple;

import org.apache.commons.lang3.tuple.Pair;

import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.trees.EnglishGrammaticalRelations;
import edu.stanford.nlp.trees.GrammaticalRelation;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TypedDependency;

public class PronounCase extends _PronounRule {

	public final int Prep = 1;
	public final int Subj = 2;
	public final int Dobj = 4;
	public final int Iobj = 8;
	public final int PossObj = 16;
	public final int PossSubj = 32;
	
	@Override
	public Object applicable(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if ( super.applicable(objects) == Rule.Inapplicable) return Rule.Inapplicable;
		return Rule.Applicable;
	}
	
	@Override
	public Object deviseRightSolution(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		BadEgg egg = (BadEgg) objects[0];
		
		Pair<?,?> pair = (Pair<?,?>) egg.whereIsWrong;
		sb.clear();
		
		if ( egg.getFlag() == this.Dobj) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			code = code ^ _PronounRule.NominativeCode;
			code = code | _PronounRule.ObjectiveCode;
			String sltn = _PronounRule.IntMapPronoun.get(code);
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("</p>");
		} else if ( egg.getFlag() == this.Iobj) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			code = code ^ _PronounRule.NominativeCode;
			code = code | _PronounRule.ObjectiveCode;
			String sltn = _PronounRule.IntMapPronoun.get(code);
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("</p>");
		} else if ( egg.getFlag() == this.Prep) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			String sltn = "";
			_ObjectTuple ot = (_ObjectTuple) pair.getKey();
			if ( "than".equals(ot.getObjectGov().label().word())) {
				code = code ^ _PronounRule.ObjectiveCode;
				code = code | _PronounRule.NominativeCode;	
			} else {
				code = code ^ _PronounRule.NominativeCode;
				code = code | _PronounRule.ObjectiveCode;
			}
			sltn = _PronounRule.IntMapPronoun.get(code);
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("</p>");
		} else if ( egg.getFlag() == this.Subj) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			code = code ^ _PronounRule.ObjectiveCode;
			code = code | _PronounRule.NominativeCode;
			String sltn = _PronounRule.IntMapPronoun.get(code);
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("</p>");
		} else if ( egg.getFlag() == this.PossObj) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			code = code ^ _PronounRule.PossessiveAdjCode;
			int code1 = code | _PronounRule.ObjectiveCode;
			int code2 = code | _PronounRule.NomCaseAndObjCaseUNKNOWNCode;
			String sltn = _PronounRule.IntMapPronoun.get(code1);
			if ( sltn == null) {
				sltn = _PronounRule.IntMapPronoun.get(code2);
			}
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("或在").append(pair.getValue()).append("后面添加一个名词");
			sb.append("</p>");
		} else if ( egg.getFlag() == this.PossSubj) {
			int code = _PronounRule.PronounMapInt.get(pair.getValue());
			code = code ^ _PronounRule.PossessiveAdjCode;
			int code1 = code | _PronounRule.NominativeCode;
			int code2 = code | _PronounRule.NomCaseAndObjCaseUNKNOWNCode;
			String sltn = _PronounRule.IntMapPronoun.get(code1);
			if ( sltn == null) {
				sltn = _PronounRule.IntMapPronoun.get(code2);
			}
			sb.append("<p>");
			sb.append("是不是该用").append(sltn);
			sb.append("或在").append(pair.getValue()).append("后面添加一个名词");
			sb.append("</p>");
		} else {
			
		}
		return sb.toString();
	}
	
	@Override
	public Object examine(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if ( this.applicable(objects) == Rule.Inapplicable) return Rule.Inapplicable;

		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];
		__SentenceElements se = (__SentenceElements) objects[1];
		
		ArrayList<BadEgg> eggList = new ArrayList<BadEgg>(16);
		/*
		 * 先检查介宾结构中有没有格错误
		 */
		if ( se.ObjectTupleList != null) {
			for( _ObjectTuple ot : se.ObjectTupleList) {
				if ( !"pobj".equals(ot.getRelation())) continue;
				Tree pObjectAncestor = ot.getObjectGovAncestor();
				if ( pObjectAncestor == null) continue;
				
				for( CoreLabel cl : pObjectAncestor.taggedLabeledYield()) {
					String word = cl.word();
					Matcher matcher = _PronounRule.PronounsNominative.matcher(word);
					if ( matcher.find() && !"than".equals(ot.getObjectGov().label().word())) {
						BadEgg egg = new BadEgg();
						egg.setViolatedRule(this);
						egg.setFlag(this.Prep);
						egg.whereIsWrong = Pair.of(ot, matcher.group());
						eggList.add(egg);
					}
					matcher = _PronounRule.PronounsObjective.matcher(word);
					if ( matcher.find() && "than".equals(ot.getObjectGov().label().word())) {
						BadEgg egg = new BadEgg();
						egg.setViolatedRule(this);
						egg.setFlag(this.Prep);
						egg.whereIsWrong = Pair.of(ot, matcher.group());
						eggList.add(egg);
					}
					matcher = _PronounRule.PronounsPossessiveAdj.matcher(word);
					if ( matcher.find()) {
						BadEgg egg = new BadEgg();
						egg.setViolatedRule(this);
						egg.setFlag(this.PossObj);
						egg.whereIsWrong = Pair.of(ot, matcher.group());
						eggList.add(egg);
					}					
				}
			}			
		}
		/*
		 * 如果没有介宾错误，把介宾结构存储起来，这样当介宾结构出现在主语成分中，就不会被认定为有错误
		 */
		Collection<?> tdl = (Collection<?>) preprocessData.get("tdl");
		HashMap<String, TypedDependency> pobjs = new HashMap<String, TypedDependency>(16);
		for( Object obj : tdl) {
			TypedDependency TD = (TypedDependency) obj;
			GrammaticalRelation reln = TD.reln();
			if( reln.equals(EnglishGrammaticalRelations.PREPOSITIONAL_OBJECT)) {
				pobjs.put(TD.dep().toString(), TD);
			}
		}
		
		/*
		 * 在主语是否存在格错误
		 */
		if ( se.NSubjTupleList != null) {
			for( _NSubjTuple nst : se.NSubjTupleList) {
				
				Tree subjectAncestor = nst.getSubjectAncestor();

				/*
				 * 主语中是否有格错误
				 */
				if ( subjectAncestor != null) {
					for( CoreLabel cl : subjectAncestor.taggedLabeledYield()) {
						String word = cl.word();
						String index = String.valueOf(cl.index()+1);
						String key = word+"-"+index;
						Matcher matcher = _PronounRule.PronounsObjective.matcher(word);
						if ( matcher.find() && pobjs.get(key) == null) {
							BadEgg egg = new BadEgg();
							egg.setViolatedRule(this);
							egg.setFlag(this.Subj);
							egg.whereIsWrong = Pair.of(nst, matcher.group());
							eggList.add(egg);
						}
						matcher = _PronounRule.PronounsPossessiveAdj.matcher(word);
						if ( matcher.find()) {
							BadEgg egg = new BadEgg();
							egg.setViolatedRule(this);
							egg.setFlag(this.PossSubj);
							egg.whereIsWrong = Pair.of(nst, matcher.group());
							eggList.add(egg);
						}
					}					
				}
			}			
		}
		/*
		 * 宾语是否存在格错误
		 */
		if ( se.ObjectTupleList != null) {
			for( _ObjectTuple ot : se.ObjectTupleList) {
				if ( "pobj".equals(ot.getRelation())) continue;
				Tree objectAncestor = ot.getObjectAncestor();
				/*
				 * 直接宾语中是否有格错误
				 */
				if ( objectAncestor != null) {
					for( CoreLabel cl : objectAncestor.taggedLabeledYield()) {
						String word = cl.word();
						String index = String.valueOf(cl.index()+1);
						String key = word+"-"+index;
						TypedDependency TD = pobjs.get(key);
						Matcher matcher = _PronounRule.PronounsNominative.matcher(word);
						if ( matcher.find() &&  TD!= null && "than".equals(TD.gov().label().word())) {
							BadEgg egg = new BadEgg();
							egg.setViolatedRule(this);
							if ( "dobj".equals(ot.getRelation())) {
								egg.setFlag(this.Dobj);
							} else if ( "iobj".equals(ot.getRelation())) {
								egg.setFlag(this.Iobj);
							}
							
							egg.whereIsWrong = Pair.of(ot, matcher.group());
							eggList.add(egg);
						}
						matcher = _PronounRule.PronounsPossessiveAdj.matcher(word);
						if ( matcher.find()) {
							BadEgg egg = new BadEgg();
							egg.setViolatedRule(this);
							egg.setFlag(this.PossObj);
							egg.whereIsWrong = Pair.of(ot, matcher.group());
							eggList.add(egg);
						}					
					}			
				}
			}
		}
		if ( eggList.size() > 0) return eggList;
		return null;
	}
	
	@Override
	public Object whyItsWrong(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		BadEgg egg = (BadEgg) objects[0];
		
		Pair<?,?> pair = (Pair<?,?>) egg.whereIsWrong;
		sb.clear();
		
		if ( egg.getFlag() == this.Dobj) {
			sb.append("<p>");
			sb.append(pair.getValue());
			sb.append("不能做宾语");
			sb.append("</p>");
		} else if ( egg.getFlag() == this.Iobj) {
			sb.append("<p>");
			sb.append(pair.getValue());
			sb.append("不能做宾语");
			sb.append("</p>");			
		} else if ( egg.getFlag() == this.Prep) {
			_ObjectTuple ot = (_ObjectTuple) pair.getKey();
			if ( "than".equals(ot.getObjectGov().label().word())) {
				sb.append("<p>");
				sb.append(pair.getValue());
				sb.append("不能做than的宾语. than后面的代词应当使用主格.");
				sb.append("</p>");					
			} else {
				sb.append("<p>");
				sb.append(pair.getValue());
				sb.append("不能做介词宾语");
				sb.append("</p>");	
			}
		} else if ( egg.getFlag() == this.Subj) {
			sb.append("<p>");
			sb.append(pair.getValue());
			sb.append("不能做主语");
			sb.append("</p>");			
		} else if ( egg.getFlag() == this.PossObj) {
			sb.append("<p>");
			sb.append(pair.getValue());
			sb.append("不能做宾语");
			sb.append("</p>");
		} else if ( egg.getFlag() == this.PossSubj) {
			sb.append("<p>");
			sb.append(pair.getValue());
			sb.append("不能做主语");
			sb.append("</p>");	
		} else {
			
		}
		return sb.toString();
	}
}
